package triDemo;


import java.awt.event.*;
import java.io.*;
import java.util.*;

import triEngine.*;
import triBasic.*;
import utils.Constants;

public class Instance implements ActionListener {

	private RunWindow window;
	
	private TriEngine engine;
	
	public static final String InsertOp = "i";
	public static final String RemoveOp = "r";
	public static final String QueryItemOp = "qi";
	public static final String QuerySetOp = "qs";
	public static final String QueryTagOp = "qt";
	
	public Instance() {
	}
	
	public void setDisplay(RunWindow w) {
		this.window = w;
	}
	
	
	@Override
	public void actionPerformed(ActionEvent e) {
		Object obj = e.getSource();
		
		
		if (obj == window.startButton) {
			System.out.println("click on start...");
			
			engine = new TriEngine();
			engine.StartUp();
		}
		else if (obj == window.closeButton) {
			System.out.println("click on close...");
			
			engine.ShutDown();
			engine = null;
		}
		else if (obj == window.runButton) {
			System.out.println("click on run....");
			execute(window.getFileName());
		}
		else if (obj == window.clearFileButton) {
			System.out.println("click on clear all....");
			clearAll();
		}
		else if (obj == window.clearLogButton) {
			System.out.println("click on clear log");
			clearLog();
		}
	}
	
	private void execute(String filename) {
		Scanner scanner;
		String op;
		TagList path;
		TriItem item;
		
		try {
			scanner = new Scanner(new FileInputStream(filename));
			while (scanner.hasNext()) {
				op = scanner.next();
				
				if (op.equals("#")) {
					scanner.nextLine();
					continue;
				}
				
				if (op.equals(Instance.InsertOp)) {
					item = new DemoItem(scanner.next());
					path = parseTriPath(scanner);
					insert(item, path);
				}
				else if (op.equals(Instance.RemoveOp)) {
					item = new DemoItem(scanner.next());
					path = parseTriPath(scanner);
					remove(item, path);
				}
				else if (op.equals(Instance.QuerySetOp)) {
					path = parseTriPath(scanner);
					querySet(path);
				}
				else if (op.equals(Instance.QueryItemOp)) {
					item = new DemoItem(scanner.next());
					queryItem(item);
				}
				else if (op.equals(Instance.QueryTagOp)){
					queryTag(scanner.next());
				}
				
			}
			scanner.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	private void insert(TriItem item, TagList path) {
		engine.insert(item, path);
		window.display("Insert item = " + item.convert2String() + ", path = " + path2String(path));
	}
	
	private void remove(TriItem item, TagList path) {
		engine.remove(item, path);
		window.display("Remove item = " + item.convert2String() + ", path = " + path2String(path));
	}
	
	private void querySet(TagList path) {
		ISet<String> set = engine.queryItemSet(path);
		window.display("Query node, path = " + path2String(path) + ", content = " + itemset2String(set));
	}
	
	private void queryItem(TriItem item) {
		ISet<NodeInfo> set = engine.queryItem(item);
		window.display("Query item = " + item.convert2String() + ", nodes = " + nodeset2String(set));
	}
	
	private void queryTag(String tag) {
		ISet<NodeInfo> set = engine.queryTag(tag);
		window.display("Query tag = " + tag + ", nodes = " + nodeset2String(set));
	}
	
	private void clearAll() {
		deleteFile(Constants.NODE_FILENAME);
		deleteFile(Constants.SET_FILENAME);
		deleteFile(Constants.SET_FILENAME_TEMP);
		deleteFile(Constants.SET_INODE_FILENAME);
		deleteFile(Constants.SET_INODE_FILENAME_TEMP);
		deleteFile(Constants.NODE_IDX_FILENAME);
		deleteFile(Constants.NODE_IDX_META_FILENAME);
		deleteFile(Constants.TAG_IDX_FILENAME);
		deleteFile(Constants.TAG_IDX_FILENAME_TEMP);
		deleteFile(Constants.TAG_IDX_INODE_FILENAME);
		deleteFile(Constants.TAG_IDX_INODE_FILENAME_TEMP);
		deleteFile(Constants.TAG_BPTree_FILENAME);
		deleteFile(Constants.ITEM_IDX_FILENAME);
		deleteFile(Constants.ITEM_IDX_INODE_FILENAME);
		deleteFile(Constants.ITEM_BPTree_FILENAME);
	}
	
	private void clearLog() {
		deleteFile(Constants.LOG_FILENAME);
	}
	
	private void deleteFile(String filename) {
		File f = new File(filename);
		if (f.exists())
			f.delete();
	}
	
	private String nodeset2String(ISet<NodeInfo> set) {
		StringBuilder strb = new StringBuilder();	
		NodeInfo node;
		boolean isFirst = true;
		
		strb.append("{");
		while (true) {
			node = set.nextItem();
			if (node == null)
				break;
			if (!isFirst)
				strb.append(", ");
			else
				isFirst = false;
			
			strb.append("<");
			strb.append(node.getNodeId());
			strb.append(",");
			strb.append(node.getTagName());
			strb.append(">");
		}
		strb.append("}");
		
		return strb.toString();
	}
	
	private String itemset2String(ISet<String> set) {
		StringBuilder strb = new StringBuilder();	
		String item;
		boolean isFirst = true;
		
		strb.append("{");
		while (true) {
			item = set.nextItem();
			if (item == null)
				break;
			if (!isFirst)
				strb.append(", ");
			else
				isFirst = false;
			
			strb.append(item);
		}
		strb.append("}");
		
		return strb.toString();
	}
	
	private String path2String(TagList path) {
		StringBuilder strb = new StringBuilder();	
		String tag;
		boolean isFirst = true;
		
		strb.append("<");
		path.resetPos();
		while (true) {
			tag = path.nextTag();
			if (tag == null)
				break;
			if (!isFirst)
				strb.append(", ");
			else
				isFirst = false;
			
			strb.append(tag);
		}
		strb.append(">");
		
		return strb.toString();
	}
	
	private TagList parseTriPath(Scanner scanner) {
		int count = scanner.nextInt();
		Vector<String> tags = new Vector<String> (count);
		
		for (int i = 0; i < count; ++i)
			tags.add(scanner.next());
		
		
		return new TagList(tags);
	}

}

class DemoItem implements TriItem {

	private String str;
	
	public DemoItem(String s) {
		str = s;
	}
	
	@Override
	public int GetSize() {
		return str.length();
	}

	@Override
	public String convert2String() {
		return str;
	}
	
}
